#include "ExchangeAdapterConfig.h"
#include "RMMSClOrdIdManager.h"
#include "DebugUtils.h"
#include "sqlite3.h"
#include "UFile.h"
#include "ExchangeAdapterCompiler.h"

RMMS_NS_BEGIN

RMMSClOrdIdManager::RMMSClOrdIdManager(){}

RMMSClOrdIdManager::~RMMSClOrdIdManager(){}

int32 RMMSClOrdIdManager::Init()
{
	std::memset(m_clordidinfo,0,sizeof(m_clordidinfo));
	return 0;
}

void RMMSClOrdIdManager::Uninit()
{
	uint8 i = 0;
	for (;i < RMMS_EXCH_SUM;i++)
		UinitClOrdID((Exchange)i);
}

const tchar* RMMSClOrdIdManager::GetNewLocalId(Exchange exch)
{
	if(0 > AddClOrdId(exch) || 0 > WriteClOrdID(exch)){
		DecClOrdId(exch);
		return NULL;
	}
	return GetExchID(exch);
}

int32 RMMSClOrdIdManager::AddExch(Exchange exch)
{
	if (false != m_clordidinfo[exch].ballowed)
		return -1;
	if(0 >InitClOrdID(exch))
		return -1;
	return 0;
}

void RMMSClOrdIdManager::DecExch(Exchange exch)
{
	if (true != m_clordidinfo[exch].ballowed)
		return;
	UinitClOrdID(exch);
}

int32 RMMSClOrdIdManager::AddClOrdId(Exchange exch)
{
	tchar *pid = GetExchID(exch);
	for(int32 i = m_clordidinfo[exch].idlen -1;i >= 0;i--){
		if(0 == TcharInc(exch,&(pid[i])))
			return 0;
	}

	for(int32 i = m_clordidinfo[exch].idlen -1;i >= 0;i--){
		if(0 == TcharInc(exch,&(pid[i])))
			return 0;
	}

	return 0;
}

int32 RMMSClOrdIdManager::DecClOrdId(Exchange exch)
{
	tchar *pid = GetExchID(exch);
	for(int32 i = m_clordidinfo[exch].idlen -1;i >= 0;i--){
		if(0 == TcharDec(exch,&(pid[i])))
			return 0;
	}

	for(int32 i = m_clordidinfo[exch].idlen -1;i >= 0;i--){
		if(0 == TcharDec(exch,&(pid[i])))
			return 0;
	}
	
	return 0;
}

int32 RMMSClOrdIdManager::ReadClOrdID(Exchange exch)
{
	if(0 != std::fseek(m_clordidinfo[exch].cfgfilehandle,0,SEEK_SET))
		return -1;
	const tchar *pid = GetExchID(exch);
	if(m_clordidinfo[exch].idlen != std::fread((void*)pid,1,
		m_clordidinfo[exch].idlen,m_clordidinfo[exch].cfgfilehandle))
		return -1;
	return 0;
}

int32 RMMSClOrdIdManager::WriteClOrdID(Exchange exch)
{
	DBG_ASSERT(NULL != m_clordidinfo[exch].cfgfilehandle);
	if(0 != std::fseek(m_clordidinfo[exch].cfgfilehandle,0,SEEK_SET))
		return -1;
	const tchar *pid = GetExchID(exch);

	if(m_clordidinfo[exch].idlen != std::fwrite(pid,1,
		m_clordidinfo[exch].idlen,
		m_clordidinfo[exch].cfgfilehandle))
		return -1;
	return 0;
}

tchar* RMMSClOrdIdManager::GetExchID(Exchange exch)
{
	switch(exch){
	case RMMS_CN_DL:
		return m_clordidinfo[exch].dlclordid;
	case RMMS_CN_SH:
		return m_clordidinfo[exch].shclordid;
	case RMMS_CN_ZJ:
		return m_clordidinfo[exch].zjclordid;
	case RMMS_CN_ZZ:
		return m_clordidinfo[exch].zzclordid;
	case RMMS_US_CME:
		return m_clordidinfo[exch].cmeclordid;
	default:
		DBG_ASSERT(false);
		return NULL;
	}
}

void RMMSClOrdIdManager::InitExchInfo(Exchange exch)
{
	switch(exch){
	case RMMS_CN_DL:
		m_clordidinfo[exch].cfgfilename = "CNDLOrdID.cfg";
		m_clordidinfo[exch].idlen = ORD_DL_LEN;
		for(int i = 0;i < m_clordidinfo[exch].idlen;i++)
			m_clordidinfo[exch].dlclordid[i] ='0';
		m_clordidinfo[exch].dlclordid[ORD_DL_LEN]='\0';
		break;
	case RMMS_CN_ZZ:
		m_clordidinfo[exch].cfgfilename = "CNZZOrdID.cfg";
		m_clordidinfo[exch].idlen = ORD_ZZ_LEN;
		for(int i = 0;i < m_clordidinfo[exch].idlen;i++)
			m_clordidinfo[exch].zzclordid[i] ='z';
		m_clordidinfo[exch].zzclordid[ORD_ZZ_LEN]='\0';
		break;
	case RMMS_CN_ZJ:
		m_clordidinfo[exch].cfgfilename = "CNZJOrdID.cfg";
		m_clordidinfo[exch].idlen = ORD_ZJ_LEN;
		for(int i = 0;i < m_clordidinfo[exch].idlen;i++)
			m_clordidinfo[exch].zjclordid[i] ='z';
		m_clordidinfo[exch].zjclordid[ORD_ZJ_LEN]='\0';
		break;
	case RMMS_CN_SH:
		m_clordidinfo[exch].cfgfilename = "CNSHOrdID.cfg";
		m_clordidinfo[exch].idlen = ORD_SH_LEN;
		for(int i = 0;i < m_clordidinfo[exch].idlen;i++)
			m_clordidinfo[exch].shclordid[i] ='z';
		m_clordidinfo[exch].shclordid[ORD_SH_LEN]='\0';
		break;
	case RMMS_US_CME:
		m_clordidinfo[exch].cfgfilename = "USCMEOrdID.cfg";
		m_clordidinfo[exch].idlen = ORD_CME_LEN;
		for(int i = 0;i < m_clordidinfo[exch].idlen;i++)
			m_clordidinfo[exch].shclordid[i] ='z';
		m_clordidinfo[exch].shclordid[ORD_CME_LEN]='\0';
		break;
	default:
		DBG_ASSERT(false);
		break;
	}
}

int32 RMMSClOrdIdManager::InitClOrdID(Exchange exch)
{
	InitExchInfo(exch);

	if(!LIB_NS::UFile::IsFileExist(m_clordidinfo[exch].cfgfilename.c_str())){
		m_clordidinfo[exch].cfgfilehandle = std::fopen(
			m_clordidinfo[exch].cfgfilename.c_str(),"w+");
		if(0 > WriteClOrdID(exch))
			return -1;
	}else{
		m_clordidinfo[exch].cfgfilehandle = 
			std::fopen(m_clordidinfo[exch].cfgfilename.c_str(),"r+");
		ReadClOrdID(exch);
	}

	if(NULL == m_clordidinfo[exch].cfgfilehandle)
		return -1;
	
	std::fseek(m_clordidinfo[exch].cfgfilehandle,0,SEEK_END);
	if(m_clordidinfo[exch].idlen != std::ftell(
		m_clordidinfo[exch].cfgfilehandle)){
		std::fclose(m_clordidinfo[exch].cfgfilehandle);
		m_clordidinfo[exch].cfgfilehandle = NULL;
		return -1;
	}

	m_clordidinfo[exch].ballowed = true;

	return 0;
}

void RMMSClOrdIdManager::UinitClOrdID(Exchange exch)
{
	if(true != m_clordidinfo[exch].ballowed)
		return;
	std::fclose(m_clordidinfo[exch].cfgfilehandle);
	m_clordidinfo[exch].ballowed = false;
}

int32 RMMSClOrdIdManager::TcharInc(Exchange exch,tchar *poldc)
{
	if(RMMS_CN_DL == exch){
		switch(*poldc){
		case '9':
			*poldc = '0';
			return 1;
		default:
			*poldc += 1;
			break;
		}
	} else {
		switch(*poldc){
		case '9':
			*poldc = 'A';
			break;
		case 'Z':
			*poldc = 'a';
			break;
		case 'z':
			*poldc = '0';
			return 1;
		default:
			*poldc += 1;
			break;
		}
	}

	return 0;
}

int32 RMMSClOrdIdManager::TcharDec(Exchange exch,tchar *poldc)
{
	if(RMMS_CN_DL == exch){
		switch(*poldc){
		case '0':
			*poldc = '9';
			return 1;
		default:
			*poldc -= 1;
			break;
		}
	} else {
		switch(*poldc){
		case '0':
			*poldc = 'z';
			return 1;
		case 'A':
			*poldc = '0';
			break;
		case 'a':
			*poldc = 'Z';
			break;
		default:
			*poldc -= 1;
			break;
		}
	}	

	return 0;
}

RMMS_NS_END